package com.intelligent.ispc.common.persistence.jdbc;

import com.intelligent.ispc.common.persistence.Hibernates;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;

import java.util.List;

/**
 * Created by Peter on 15/11/25.
 */
public class JdbcPaginationTemplate {
    private final Logger logger = LoggerFactory.getLogger(JdbcPaginationTemplate.class);

    private JdbcTemplate jdbcTemplate;

    private JdbcPaginationTemplate() {
    }

    /**
     * new Instance
     *
     * @param jdbcTemplate
     * @return
     */
    public static JdbcPaginationTemplate newInstance(JdbcTemplate jdbcTemplate) {
        JdbcPaginationTemplate template = new JdbcPaginationTemplate();
        template.setJdbcTemplate(jdbcTemplate);
        return template;
    }


    /**
     * Using the default settings to searching.
     *
     * @param sql
     * @return
     */
    public JdbcPageable findPage(String sql) {
        checkQuery(sql);
        return findPage(sql, null, null);
    }


    public JdbcPageable findPage(String sql, JdbcPageable page) {
        checkQuery(sql);
        return findPage(sql, page, null);
    }

    /**
     * Using the default settings to searching.
     *
     * @param sql
     * @param page
     * @param mapper
     */
    public JdbcPageable findPage(String sql, JdbcPageable page, RowMapper mapper) {
        checkQuery(sql);

        StringBuffer totalSQL = new StringBuffer(" SELECT count(*) as count FROM ( ");

        int orderIndex = sql.toUpperCase().indexOf("ORDER");

        if (orderIndex != -1) {
            totalSQL.append(sql.substring(0, orderIndex));
        } else {
            totalSQL.append(sql);
        }

        totalSQL.append(" ) totalTable ");

        // total count
        page.setTotal(new Integer(getJdbcTemplate().queryForMap(totalSQL.toString()).get("count").toString()));
        // total pages.
        page.setTotalPages();
        // get begin index
        page.setBegin();
        // get end index
        page.setEnd();

        JDBCPageDialect md = JDBCPageDialect.valueOf(Hibernates.getDialectShort(this.jdbcTemplate.getDataSource()));

        String queryPageSql = md.generatePageSql(sql, page);
        // put data into the result set
        if (mapper != null) {
            List<Object> list =  getJdbcTemplate().query(queryPageSql, mapper);
            page.setContent(getJdbcTemplate().query(queryPageSql, mapper));
        } else {
            page.setContent(getJdbcTemplate().queryForList(queryPageSql));
        }

        return page;
    }


    /**
     * Check the pagination tools.
     *
     * @param sql
     * @return
     */
    private boolean checkQuery(String sql) {
        if (jdbcTemplate == null) {
            logger.warn("don't init the jdbcTemplate, Sql：[{}]", sql);
            throw new IllegalArgumentException("jdbcTemplate is null, please initial it first. ");
        } else if (sql.equals("")) {
            logger.warn("the param sql is empty.");
            throw new IllegalArgumentException("sql is empty, please initial it first. ");
        }
        return true;
    }

    public JdbcTemplate getJdbcTemplate() {
        return jdbcTemplate;
    }

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }
}
